#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

// 读写锁
pthread_rwlock_t r;
pthread_rwlock_t w;

int num = 100;


// 判断是否是2的倍数-线程函数   - 读锁
void* IfTwo(void *arg __attribute__((unused)))   
{
    // 1、将自身设置为分离属性(此线程函数结束后，自动有人给它收尸)
    pthread_detach(pthread_self());     

    // 2、正常运行的线程功能
    while (1)
    {
        pthread_rwlock_rdlock(&r);           // 读锁(共享)

        // 一段朴素的代码
        if(num%2 == 0)
            printf("%d是2的倍数\n", num);

        pthread_rwlock_unlock(&r);           
        sleep(1);                             
    }
    
    // 线程退出
    pthread_exit(NULL);
}

// 判断是否是3的倍数-线程函数   - 读锁
void* IfThree(void *arg __attribute__((unused)))   
{
    // 1、将自身设置为分离属性(此线程函数结束后，自动有人给它收尸)
    pthread_detach(pthread_self());     

    // 2、正常运行的线程功能
    while (1)
    {
        pthread_rwlock_rdlock(&r);           // 读锁(共享)

        // 一段朴素的代码
        if(num%3 == 0)
            printf("%d是3的倍数\n", num);

        pthread_rwlock_unlock(&r);           
        sleep(1);                            
    }
    
    // 线程退出
    pthread_exit(NULL);
}

// 判断是否是5的倍数-线程函数   - 读锁
void* IfFive(void *arg __attribute__((unused)))   
{
    // 1、将自身设置为分离属性(此线程函数结束后，自动有人给它收尸)
    pthread_detach(pthread_self());     

    // 2、正常运行的线程功能
    while (1)
    {
        pthread_rwlock_rdlock(&r);           // 读锁(共享)

        // 一段朴素的代码
        if(num%5 == 0)
            printf("%d是5的倍数\n", num);

        pthread_rwlock_unlock(&r);           
        sleep(1);                           
    }
    
    // 线程退出
    pthread_exit(NULL);
}


// 获取随机数-线程函数  - 写锁
void* GetSrand(void *arg __attribute__((unused)))    
{
    // 1、将自身设置为分离属性(此线程函数结束后，自动有人给它收尸)
    pthread_detach(pthread_self());     

    // 2、正常运行的线程功能
    int count = 0;
    while (1)
    {
        pthread_rwlock_wrlock(&w);                 // 加写锁(这个人上了唯一的厕所)

        num = rand() % 5000;  
        printf("随机获取的数据num = %d\n", num);

        pthread_rwlock_unlock(&w);                // 解写锁(这个人从厕所里出来了)
        sleep(1);
    }

    // 线程退出
    pthread_exit(NULL);

}

// 获取随机数-线程函数  - 写锁
void* GetAddNum(void *arg __attribute__((unused)))    
{
    // 1、将自身设置为分离属性(此线程函数结束后，自动有人给它收尸)
    pthread_detach(pthread_self());     

    // 2、正常运行的线程功能
    int count = 0;
    while (1)
    {
        pthread_rwlock_wrlock(&w);                 // 加写锁(这个人上了唯一的厕所)

        num = num + 1;
        printf("自加的数据num = %d\n", num);

        pthread_rwlock_unlock(&w);                 // 解写锁(这个人从厕所里出来了)
        sleep(1);
    }

    // 线程退出
    pthread_exit(NULL);

}


// 读写锁
int main(int argc, char const *argv[])
{
    // 1、动态初始化读写锁
    pthread_rwlock_init(&r, NULL);
    pthread_rwlock_init(&w, NULL);

    // 2、创建并运行线程函数
    pthread_t IfTwo_tid;
    pthread_t IfThree_tid;
    pthread_t IfFive_tid;
    pthread_t GetSrand_tid;
    pthread_t GetAddNum_tid;

    pthread_create(&IfTwo_tid, NULL, IfTwo, NULL);
    pthread_create(&IfThree_tid, NULL, IfThree, NULL);
    pthread_create(&IfFive_tid, NULL, IfFive, NULL);
    pthread_create(&GetSrand_tid, NULL, GetSrand, NULL);
    pthread_create(&GetAddNum_tid, NULL, GetAddNum, NULL);

    // 3、主线程
    while (1)
    {
        sleep(1);
    }
    
    // 4、销毁读写锁
    pthread_rwlock_destroy(&r);
    pthread_rwlock_destroy(&w);
    
    return 0;
}
